;;; net.scm --- Net services

;; Copyright © 2015, 2019 Alex Kost

;; Author: Alex Kost <alezost@gmail.com>
;; Created: 14 Feb 2015

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <http://www.gnu.org/licenses/>.

;;; Commentary:

;; Various network services.

;;; Code:

(define-module (al guix services net)
  #:use-module (gnu services)
  #:use-module (gnu services shepherd)
  #:use-module (guix gexp)
  #:use-module (guix records)
  #:use-module (gnu packages linux)
  #:use-module (ice-9 match)
  #:export (net-static-service-type))

(define-record-type* <net-static>
  net-static make-net-static
  net-static?
  (interface net-static-interface)
  (ip-address net-static-ip-address)
  (gateway net-static-gateway)
  (name-servers net-static-name-servers))

(define net-static-service-type
  (shepherd-service-type
   'net-static
   (match-lambda
     (($ <net-static> interface ip-address gateway name-servers)
      (let ((ip #~(string-append #$iproute "/sbin/ip")))
        (shepherd-service
         (documentation "Networking interface with a static IP.")
         (provision '(networking))
         ;; Wait for udev to be sure that INTERFACE is usable.
         (requirement '(udev))

         (start
          #~(lambda _
              ;; Return #t if successfully started.
              (and (zero? (system* #$ip "link" "set"
                                   "dev" #$interface "up"))
                   (zero? (system* #$ip "address" "add"
                                   #$ip-address "dev" #$interface))
                   (zero? (system* #$ip "route" "add"
                                   "default" "via" #$gateway))
                   #$(when (pair? name-servers)
                       #~(call-with-output-file "/etc/resolv.conf"
                           (lambda (port)
                             (display
                              "# Generated by 'net-static-service'.\n"
                              port)
                             (for-each (lambda (server)
                                         (format port "nameserver ~a~%"
                                                 server))
                                       '#$name-servers)))))
              #t))
         (stop
          #~(lambda _
              ;; Return #f is successfully stopped.
              (not
               (and (zero? (system* #$ip "address" "flush"
                                    "dev" #$interface))
                    (zero? (system* #$ip "link" "set"
                                    "dev" #$interface "down"))))))
         (respawn? #f)))))))

;;; net.scm ends here
